#ifndef _WIN32
#include <netdb.h>
#include <arpa/inet.h>
#include <sys/time.h>
#else
#include <WinSock2.h>
#include <WS2tcpip.h>
#include <Windows.h>
#include <time.h>
#endif

#include <string.h>
#include <errno.h>
#include <stdlib.h>
#include "common.h"
#include "utils.h"
long long systemCurrentTime(void)
{
#ifdef _WIN32
	DWORD start;
	start = GetTickCount64();
	return start;
#else
	struct timeval objNow;
	gettimeofday(&objNow, NULL);
	return objNow.tv_sec * 1000 + (objNow.tv_usec / 1000);
#endif
}

//long long  getFileSize(char* filePath) {
//	FILE* file = fopen(filePath, "r");

//	if (NULL == file) {
//		LOGW("file cannot be open");
//		return 0L;
//	}
//	long long curpos, length;
//	curpos = ftell(file);
//	fseek(file, 0L, SEEK_END);
//	length = ftell(file);
//	fseek(file, curpos, SEEK_SET);
//	fclose(file);
//	return length;
//}
//
//char* conactString(char *s1, char *s2) {
//	char *result = (char*)malloc(strlen(s1) + strlen(s2) + 1); //+1 for the zero-terminator
//	//in real code you would check for errors in malloc here
//	if (result == NULL)
//		return NULL;
//
//	strcpy(result, s1);
//	strcat(result, s2);
//	return result;
//}
//
//int readFile(char * outbuf, int fileSize, int filePathSize, char* filePath) {
//
//	LOGI("file:%s[ %d bytes]", filePath, fileSize);
//	FILE* file = fopen(filePath, "r");
//	if (NULL == file) {
//		LOGW("file cannot be open");
//		return -1; 
//	}
//	fseek(file, 0L, SEEK_END); 
//	int flen = ftell(file); 
//	if (fileSize != flen) {
//		LOGW("fileSize is error %d,%d", fileSize, flen);
//		return -1;
//	}
//	fseek(file, 0L, SEEK_SET);
//	fread(outbuf, flen, 1, file);
//	LOGW("file content:%s", outbuf);
//	fclose(file);
//	file = NULL; 
//	return -1;
//}
//int readFileAtPostion(FILE * file, char * outbuf, int pos, int len) {
//	int seeked = fseek(file, pos, SEEK_SET); 
//	if (seeked < 0) {
//		LOGW("fseek fail:pos:%d,seeked:%d", pos, seeked);
//		return 0;
//	}
//	return fread(outbuf, 1, len, file);
//}
//
//int writeFileAtPostion(char* filePath, char * inbuf, int pos, int len) {
//	LOGI("*** writeFile: %s [curWritePos: %d bytes, length: %d] ***", filePath, pos, len);
//
//	FILE* file;
//	if (pos == 0)
//	{
//		file = fopen(filePath, "wb");
//	}
//	else
//	{
//		file = fopen(filePath, "ab");
//	}
//
//	if (NULL == file)
//	{
//		LOGW("##### File=%s cannot be open: errno:%d, error: [%s]", filePath, errno, strerror(errno));
//		return -1l;
//	}
//
//	fseek(file, pos, SEEK_SET);
//	long long writed = fwrite(inbuf, 1, len, file);
//	fclose(file);
//	file = NULL;
//	return writed;
//}
//int writeFile(char * inbuf, int fileSize, int filePathSize, char* filePath) {
//	LOGI("file:%s[ %d bytes]", filePath, fileSize);
//	FILE* file = fopen(filePath, "w");
//	if (NULL == file) {
//		LOGW("file cannot be open");
//		return -1; 
//	}
//
//	fseek(file, 0L, SEEK_SET); 
//	fwrite(inbuf, fileSize, 1, file);
//	LOGW("file content:%s", inbuf);
//	fclose(file);
//	file = NULL; 
//	return -1;
//}

void threadSleep(int millSecond)
{
#ifndef _WIN32
	usleep(millSecond * 1000);
#else
	Sleep(millSecond);
#endif//
}
void host2Ip(const char *host,char *ip,int ipLength){
	struct hostent *hptr = gethostbyname(host);
	if (!hptr) {
		LOGE("gethost");
		if (errno) {
			LOGE("err no[%d,%s]", errno, strerror(errno));
		}
		return;
	}

	char **pptr = NULL;
	switch (hptr->h_addrtype)
	{
	case AF_INET:
	case AF_INET6:
		pptr = hptr->h_addr_list;
		while (*pptr) {
			if (inet_ntop(hptr->h_addrtype, *pptr, ip, ipLength)) {
				LOGI("address: %s\n", ip);
				return;
			}
			else {
				LOGE("inet_ntop, errno[%d,%s]", errno, strerror(errno));
			}
			++pptr;
		}
		break;
	default:
		LOGI("unknown address type\n");
	}
}

//int readable_timeo(int fd, int sec)
//{
//	fd_set rset;
//	struct timeval tv;
//
//	FD_ZERO(&rset);
//	FD_SET(fd, &rset);
//
//	tv.tv_sec = sec;
//	tv.tv_usec = 0;
//
//	return (select(fd + 1, &rset, NULL, NULL, &tv));
//}
//
//std::string UrlDecode(const std::string& szToDecode)
//{
//	std::string result;
//	int hex = 0;
//	for (size_t i = 0; i < szToDecode.length(); ++i)
//	{
//		switch (szToDecode[i])
//		{
//		case '+':
//			result += ' ';
//			break;
//		case '%':
//			if (isxdigit(szToDecode[i + 1]) && isxdigit(szToDecode[i + 2]))
//			{
//				std::string hexStr = szToDecode.substr(i + 1, 2);
//				hex = strtol(hexStr.c_str(), 0, 16);


//				if (!((hex >= 48 && hex <= 57) || //0-9
//					(hex >= 97 && hex <= 122) ||   //a-z
//					(hex >= 65 && hex <= 90) ||    //A-Z]
//					hex == 0x21 || hex == 0x24 || hex == 0x26 || hex == 0x27 || hex == 0x28 || hex == 0x29
//					|| hex == 0x2a || hex == 0x2b || hex == 0x2c || hex == 0x2d || hex == 0x2e || hex == 0x2f
//					|| hex == 0x3A || hex == 0x3B || hex == 0x3D || hex == 0x3f || hex == 0x40 || hex == 0x5f
//					))
//				{
//					result += char(hex);
//					i += 2;
//				}
//				else result += '%';
//			}
//			else {
//				result += '%';
//			}
//			break;
//		default:
//			result += szToDecode[i];
//			break;
//		}
//	}
//	return result;
//}
extern "C" {
	int isOpenLogTxt = 0;

	EXPORT  int openLogTxt() {
#ifndef __ANDROID__
		if (isOpenLogTxt==0) {
			LOGW(" stdout > gl-log.txt ");
			if (freopen("gl-log.txt", "w", stdout) == NULL) {
				LOGW("freopen log fail");
				return -1;
			}
			isOpenLogTxt = 1;

		}
#endif
		return 0;
	}

	EXPORT  void closeLogTxt() {
		if (isOpenLogTxt) {
			fclose(stdout);
			isOpenLogTxt = 0;
		}
	}
}


char* cacheFilePath = NULL;
char* cacheFileData = NULL;
int cacheFileSize = 0;

char* g_read_string_from_file(const char * _file_path, int &_size)
    {
    if (cacheFilePath == NULL)
        {
        cacheFilePath = (char*)malloc(MAXSIZE_FILEPATH);
        memset(cacheFilePath, 0, MAXSIZE_FILEPATH);
        cacheFileData = (char*)malloc(MAXSIZE_FILEDATA);
        memset(cacheFileData, 0, MAXSIZE_FILEDATA);
        }

    if (strcmp(_file_path, cacheFilePath) == 0)
        {
                LOGI("hit cache");
        _size = cacheFileSize;
        return cacheFileData;
        }
    const int SIZE = 256;
    char tmp[SIZE];
    FILE *fp = fopen(_file_path, "rb");
    fseek(fp, 0L, SEEK_END);
    int size = ftell(fp);
    fseek(fp, 0L, SEEK_SET);
    char *str = (char*)malloc(sizeof(char) * size + 1);
    int pos = 0;
    while (true) {
        size_t read = fread(tmp, sizeof(char), SIZE, fp);
        memcpy(str + pos, tmp, read);
        pos += read;

        if (read < SIZE) {
            break;
            }
        }
    str[size] = 0;
    fclose(fp);
    _size = size;

    if (MAXSIZE_FILEDATA>size)
    {
        memcpy(cacheFilePath, _file_path, strlen(_file_path));
        memcpy(cacheFileData, str, size);
        _size = cacheFileSize;
    }

    return str;
    }